package com.yuanss.smart.framework.proxy;

import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

/**
 * @Description 代理链
 * 所谓链式代理，也就是说，可将多个代理通过一条链子串起来，一个个地去执行，执行顺序取决于添加到链上的先后顺序。
 * @Date 2024/11/14 下午3:20
 * @Created by 菜到不敢run
 */
public class ProxyChain {
    // 要代理的目标类
    private final Class<?> targetClass;
    // 要代理的目标对象
    private final Object targetObject;
    // 要代理的目标方法
    private final Method targetMethod;
    // 目标方法的代理(这个是CGLib为我们提供的)
    private final MethodProxy methodProxy;
    // 要代理的目标方法的方法参数
    private final Object[] methodParams;

    // 代理列表
    private List<Proxy> proxyList = new ArrayList<Proxy>();
    // 代理索引
    private int proxyIndex = 0;

    // ProxyChain构造函数
    public ProxyChain(Class<?> targetClass, Object targetObject, Method targetMethod,
                      MethodProxy methodProxy, Object[] methodParams, List<Proxy> proxyList) {
        this.targetClass = targetClass;
        this.targetObject = targetObject;
        this.targetMethod = targetMethod;
        this.methodProxy = methodProxy;
        this.methodParams = methodParams;
        this.proxyList = proxyList;
    }

    public Class<?> getTargetClass() {
        return targetClass;
    }

    public Method getTargetMethod() {
        return targetMethod;
    }

    public Object[] getMethodParams() {
        return methodParams;
    }

    /**
     * 如果尚未达到proxyList上限，则从proxyList上拿取相应的对象，执行它的doProxy方法，
     * 在Proxy接口的实现中会提供相应的横切逻辑，并调用doProxyChain方法，随后将再次调用
     * 当前ProxyChain对象的doProxyChain方法，知道proxyIndex达到proxyList上限为止，
     * 到最后再调用methodProxy的invokeSuper方法，执行目标对象的业务逻辑。
     */
    public Object doProxyChain() throws Throwable{
        Object methodResult;
        if (proxyIndex < proxyList.size()) {
            methodResult = proxyList.get(proxyIndex++).doProxy(this);
        } else {
            methodResult = methodProxy.invokeSuper(targetObject, methodParams);
        }
        return methodResult;
    }
}
